package org.whh.automatic.ui.dialog;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.Serial;

/**
 * 快捷键录制对话框
 * <p>
 * 用于录制用户输入的键盘快捷键组合。
 * 主要功能：
 * 1. 显示操作说明，指导用户如何录制快捷键。
 * 2. 实时显示按下的按键组合。
 * 3. 支持修饰键（Ctrl、Alt、Shift、Win）与普通键组合。
 * 4. 支持确认和取消操作。
 * <p>
 * 典型用法：
 * ShortcutRecorderDialog dialog = new ShortcutRecorderDialog(parent);
 * dialog.setVisible(true);
 * if (dialog.isShortcutRecorded()) {
 * String shortcut = dialog.getRecordedShortcut();
 * // 使用录制的快捷键
 * }
 */
public class ShortcutRecorderDialog extends JDialog {
    @Serial
    private static final long serialVersionUID = 1L;

    private JLabel statusLabel;
    private JLabel recordedKeysLabel;
    private boolean isRecording = false;
    private boolean shortcutRecorded = false;
    private String recordedShortcut = "";
    private JButton startButton;
    private JButton confirmButton;
    private JButton cancelButton;
    private StringBuilder keysPressed = new StringBuilder();
    private String currentKeyCombo = "";

    public ShortcutRecorderDialog(JDialog parent) {
        super(parent, "录制快捷键", true);

        // 设置对话框不处理Alt+F4关闭事件
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

        // 添加窗口关闭监听器以允许通过窗口X按钮关闭
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent e) {
                dispose();
            }
        });

        JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
        mainPanel.setBackground(Color.WHITE);
        JPanel infoPanel = new JPanel();
        infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
        infoPanel.setBackground(Color.WHITE);
        JLabel titleLabel = new JLabel("快捷键录制工具");
        titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
        titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        infoPanel.add(titleLabel);
        infoPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        JLabel instructionsLabel = new JLabel("<html>1. 点击\"开始录制\"按钮<br>2. 按下要录制的快捷键组合<br>3. 松开所有按键后自动完成录制<br>4. 点击\"确认\"保存快捷键</html>");
        instructionsLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        instructionsLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        infoPanel.add(instructionsLabel);
        infoPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        statusLabel = new JLabel("就绪，等待开始录制...");
        statusLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        statusLabel.setForeground(new Color(80, 80, 80));
        statusLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        infoPanel.add(statusLabel);
        infoPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        recordedKeysLabel = new JLabel("");
        recordedKeysLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
        recordedKeysLabel.setForeground(Color.BLUE);
        recordedKeysLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        infoPanel.add(recordedKeysLabel);
        infoPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        mainPanel.add(infoPanel, BorderLayout.CENTER);
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0));
        buttonPanel.setBackground(Color.WHITE);
        startButton = new JButton("开始录制");
        startButton.addActionListener(e -> {
            if (!isRecording) {
                startRecording();
            } else {
                stopRecording();
            }
        });
        confirmButton = new JButton("确认");
        confirmButton.setEnabled(false);
        confirmButton.addActionListener(e -> {
            shortcutRecorded = true;
            dispose();
        });
        cancelButton = new JButton("取消");
        cancelButton.addActionListener(e -> dispose());
        buttonPanel.add(startButton);
        buttonPanel.add(confirmButton);
        buttonPanel.add(cancelButton);
        mainPanel.add(buttonPanel, BorderLayout.SOUTH);
        setContentPane(mainPanel);
        setSize(350, 300);
        setLocationRelativeTo(parent);
        setupKeyEventHandling();
    }

    /**
     * 重写键盘事件处理方法，阻止系统处理Alt+F4等快捷键
     */
    @Override
    protected void processKeyEvent(KeyEvent e) {
        if (isRecording && e.getID() == KeyEvent.KEY_PRESSED) {
            // 当正在录制时，阻止默认处理
            e.consume();
        }
        super.processKeyEvent(e);
    }

    // 添加键盘事件处理器
    private void setupKeyEventHandling() {
        // 使用全局键盘焦点管理器捕获键盘事件
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventDispatcher(e -> {
                    if (isRecording && isActive() && isVisible()) {
                        if (e.getID() == KeyEvent.KEY_PRESSED) {
                            processKeyPressed(e.getKeyCode());
                            e.consume(); // 消费事件，防止系统处理
                            return true; // 表示已处理事件
                        } else if (e.getID() == KeyEvent.KEY_RELEASED) {
                            processKeyReleased(e.getKeyCode());
                            e.consume(); // 消费事件，防止系统处理
                            return true; // 表示已处理事件
                        }
                    }
                    return false;
                });
    }

    /**
     * 处理按键按下事件
     * <p>
     * 记录按下的按键，并更新显示：
     * - 将按键添加到按键列表
     *
     * @param keyCode 按键代码
     */
    private void processKeyPressed(int keyCode) {
        // 特殊处理Esc键：当正在录制时，按Esc取消录制
        if (keyCode == KeyEvent.VK_ESCAPE && isRecording) {
            cancelRecording();
            return;
        }

        String keyText = getKeyText(keyCode);
        if (keysPressed.indexOf(keyText) == -1) {
            if (keysPressed.length() > 0) {
                keysPressed.append("+");
            }
            keysPressed.append(keyText);
            currentKeyCombo = keysPressed.toString();
            recordedKeysLabel.setText(currentKeyCombo);
        }
    }

    /**
     * 处理按键释放事件
     * <p>
     * 从按键列表中移除释放的按键：
     * - 如果所有按键都已释放，停止录制
     * - 如果还有按键未释放，继续录制
     *
     * @param keyCode 按键代码
     */
    private void processKeyReleased(int keyCode) {
        String keyText = getKeyText(keyCode);
        int startIndex = keysPressed.indexOf(keyText);
        if (startIndex != -1) {
            int endIndex = startIndex + keyText.length();
            if (endIndex < keysPressed.length() && keysPressed.charAt(endIndex) == '+') {
                endIndex++;
            } else if (startIndex > 0 && keysPressed.charAt(startIndex - 1) == '+') {
                startIndex--;
            }
            keysPressed.delete(startIndex, endIndex);
            recordedKeysLabel.setText(keysPressed.length() > 0 ? keysPressed.toString() : currentKeyCombo);
            if (keysPressed.length() == 0) {
                stopRecording();
            }
        }
    }

    /**
     * 判断是否是最后一个修饰键
     *
     * @param keyCode 按键代码
     * @return true表示是修饰键，false表示不是
     */
    private boolean isLastModifierKey(int keyCode) {
        return keyCode == KeyEvent.VK_SHIFT ||
                keyCode == KeyEvent.VK_CONTROL ||
                keyCode == KeyEvent.VK_ALT ||
                keyCode == KeyEvent.VK_META;
    }

    /**
     * 开始录制
     * <p>
     * 重置状态并开始录制：
     * 1. 清空按键列表
     * 2. 更新UI状态
     * 3. 禁用确认按钮
     */
    private void startRecording() {
        isRecording = true;
        keysPressed.setLength(0);
        currentKeyCombo = "";
        recordedKeysLabel.setText("");
        statusLabel.setText("正在录制，请按下快捷键组合...");
        statusLabel.setForeground(Color.BLUE);
        startButton.setText("停止录制");
        confirmButton.setEnabled(false);
        startButton.setFocusable(false);
        confirmButton.setFocusable(false);
        cancelButton.setFocusable(false);
        getRootPane().setDefaultButton(null);
    }

    /**
     * 停止录制
     * <p>
     * 完成录制并更新状态：
     * 1. 保存录制结果
     * 2. 更新UI状态
     * 3. 启用确认按钮
     */
    private void stopRecording() {
        isRecording = false;
        recordedShortcut = currentKeyCombo;
        statusLabel.setText("录制完成，点击\"确认\"保存快捷键。");
        statusLabel.setForeground(Color.GREEN.darker());
        startButton.setText("重新录制");
        confirmButton.setEnabled(true);
        startButton.setFocusable(true);
        confirmButton.setFocusable(true);
        cancelButton.setFocusable(true);
    }

    /**
     * 取消录制
     */
    private void cancelRecording() {
        isRecording = false;
        keysPressed.setLength(0);
        currentKeyCombo = "";
        recordedKeysLabel.setText("");
        statusLabel.setText("录制已取消，可重新开始录制。");
        statusLabel.setForeground(new Color(80, 80, 80));
        startButton.setText("开始录制");
        confirmButton.setEnabled(false);
        startButton.setFocusable(true);
        confirmButton.setFocusable(true);
        cancelButton.setFocusable(true);
    }

    /**
     * 获取按键的显示文本
     * <p>
     * 将按键代码转换为可读的文本：
     * - 修饰键：Ctrl、Alt、Shift等
     * - 功能键：F1-F12
     * - 普通键：字母、数字等
     *
     * @param keyCode 按键代码
     * @return 按键显示文本
     */
    private String getKeyText(int keyCode) {
        return switch (keyCode) {
            case KeyEvent.VK_CONTROL -> "Ctrl";
            case KeyEvent.VK_ALT -> "Alt";
            case KeyEvent.VK_SHIFT -> "Shift";
            case KeyEvent.VK_META, KeyEvent.VK_WINDOWS -> "Win";
            case KeyEvent.VK_ESCAPE -> "Esc";
            case KeyEvent.VK_TAB -> "Tab";
            case KeyEvent.VK_CAPS_LOCK -> "Caps";
            case KeyEvent.VK_ENTER -> "Enter";
            case KeyEvent.VK_BACK_SPACE -> "Backspace";
            case KeyEvent.VK_DELETE -> "Del";
            case KeyEvent.VK_SPACE -> "Space";
            case KeyEvent.VK_HOME -> "Home";
            case KeyEvent.VK_END -> "End";
            case KeyEvent.VK_PAGE_UP -> "PgUp";
            case KeyEvent.VK_PAGE_DOWN -> "PgDn";
            case KeyEvent.VK_INSERT -> "Ins";
            case KeyEvent.VK_PAUSE -> "Pause";
            case KeyEvent.VK_SCROLL_LOCK -> "Scroll";
            case KeyEvent.VK_PRINTSCREEN -> "PrtSc";
            case KeyEvent.VK_NUM_LOCK -> "NumLock";
            case KeyEvent.VK_LEFT -> "←";
            case KeyEvent.VK_RIGHT -> "→";
            case KeyEvent.VK_UP -> "↑";
            case KeyEvent.VK_DOWN -> "↓";
            case KeyEvent.VK_MULTIPLY -> "Num *";
            case KeyEvent.VK_ADD -> "Num +";
            case KeyEvent.VK_SUBTRACT -> "Num -";
            case KeyEvent.VK_DECIMAL -> "Num .";
            case KeyEvent.VK_DIVIDE -> "Num /";
            case KeyEvent.VK_NUMPAD0 -> "Num 0";
            case KeyEvent.VK_NUMPAD1 -> "Num 1";
            case KeyEvent.VK_NUMPAD2 -> "Num 2";
            case KeyEvent.VK_NUMPAD3 -> "Num 3";
            case KeyEvent.VK_NUMPAD4 -> "Num 4";
            case KeyEvent.VK_NUMPAD5 -> "Num 5";
            case KeyEvent.VK_NUMPAD6 -> "Num 6";
            case KeyEvent.VK_NUMPAD7 -> "Num 7";
            case KeyEvent.VK_NUMPAD8 -> "Num 8";
            case KeyEvent.VK_NUMPAD9 -> "Num 9";
            case KeyEvent.VK_F1 -> "F1";
            case KeyEvent.VK_F2 -> "F2";
            case KeyEvent.VK_F3 -> "F3";
            case KeyEvent.VK_F4 -> "F4";
            case KeyEvent.VK_F5 -> "F5";
            case KeyEvent.VK_F6 -> "F6";
            case KeyEvent.VK_F7 -> "F7";
            case KeyEvent.VK_F8 -> "F8";
            case KeyEvent.VK_F9 -> "F9";
            case KeyEvent.VK_F10 -> "F10";
            case KeyEvent.VK_F11 -> "F11";
            case KeyEvent.VK_F12 -> "F12";
            default -> KeyEvent.getKeyText(keyCode);
        };
    }

    /**
     * 获取是否已录制快捷键
     *
     * @return true表示已录制，false表示未录制或取消
     */
    public boolean isShortcutRecorded() {
        return shortcutRecorded;
    }

    /**
     * 获取录制的快捷键文本
     *
     * @return 快捷键组合的文本表示
     */
    public String getRecordedShortcut() {
        return recordedShortcut;
    }
} 